#pragma once

#include "base/uncopyable.hpp"
#include "event/loop.hpp"
#include "fmt/core.h"
#include "network/buffered_fd.hpp"
#include "network/byte_stream.hpp"
#include "network/sockaddr.hpp"
#include "network/socket_fd.hpp"

namespace ibox::network {
using namespace ibox::base;
class TcpConnection : public Uncopyable, public ByteStream {
    friend class TcpAcceptor;
    friend class TcpConnector;
    using DisconnectedCallback = std::function<void()>;

public:
    //~TcpConnection() override = default;
    ~TcpConnection() override { fmt::print("~TcpConnection()\n"); };

public:
    // 思考: TcpConnection可以拷贝吗?
    // 不应该
    TcpConnection(event::Loop *wp_loop, SocketFd fd, const SockAddr &peer_addr);
    void set_disconnected_callback(DisconnectedCallback cb) {
        m_disconnected_cb = std::move(cb);
    }
    // 主动断开
    bool disconnect();
    bool shutdown(int howto);

    // 这里返回地址好一点, 返回SockAddr每次都得拷贝一次
    const SockAddr *peer_addr() const { return &m_peer_addr; }
    SocketFd socket_fd() const;

    // 是否已经失效了
    bool is_expired() const { return m_buffd == nullptr; }

    void *set_context(void *new_context);
    void *get_context() const { return m_context; }

public:
    // 实现ByteStream的接口
    void set_receive_callback(ReceiveCallback cb, size_t threshold) override;
    void bind(ByteStream *receiver) override;
    void unbind() override;
    bool send(const void *data_ptr, size_t data_size) override;

protected:
    void on_socket_closed();
    void on_error(int errnum);

private:
    void enable();

private:
    event::Loop *m_loop{};
    std::unique_ptr<BufferedFd> m_buffd{};
    SockAddr m_peer_addr{};

    DisconnectedCallback m_disconnected_cb{};
    void *m_context{};
};

} // namespace ibox::network
